/**
 * Struttura rappresentante un nodo.
 * @param {Object} val DOM del metadato relativo all'expression
 */
function wNode(val)
{
	/**
	 * DOM di metadati/expression
	 */
	this.val = val;
	/**
	 * Contenuto di eidentifier
	 */
	this.eidentifier = val.getElementsByTagName('eidentifier')[0].innerText;
	/**
	 * Puntatore al "wNode" padre
	 */
	this.father = null;
	/**
	 * Array di puntatori ai nodi figli
	 */
	this.sons = new Array();
	
	/**
	 * Aggiunge un figlio al nodo
	 * @param {Object} node wNode del figlio da aggiungere
	 * @return {Object} Ritorna il numero totale di figli
	 */
	this.addSon = function(node)
	{
		return sons.push(node);
	}

	/**
	 * Restituisce il valore del dato elemento dublin core 
	 * @param {Object} dcElement Elemento dublin core di cui restituire il valore
	 * @param {Object} index Eventuale indice dell'elemento (eventualmente null)
	 * @return {Object} Ritorna l'innerText del dato elemento
	 */
	this.getValOf = function(dcElement,index)
	{
		if (index == null) index = 0; 
		return val.getElementsByTagName(dcElement)[index].innerText;
	}

	
}


/**
 * Classe che si occupa di ricostruire la struttura logica di un work
 * @param {Object} widentifier widentifier del work di cui si dovra` ricostruire la struttura
 * @param {Object} dataSource Oggetto DataSource che si riferisce al DS di provenienza
 */
function AnalizeWork(widentifier,dataSource)
{
	/**
	 * Funzione chiamata una volta che il servizio diventa attivo. Viene passato il
	 * riferimento a this
	 */
	this.onready = null;
	
	/**
	 * Mantiene quei nodi che non hanno un'expression genitore
	 */
	var roots = Array();
	
	/**
	 * Contiene quei nodi che ancora non han trovato il papa`
	 */
	var pending = Array();
	
	/**
	 * Contiene le informazioni sul work
	 */
	var workInformations;

	/**
	 * Ricerca ricorsivamente nell'albero la presenza di un eidentifier
	 * @param {Object} eidentifier eidentifier soggetto della ricerca
	 * @param {Object} wNodeArr Array di nodi nel quale cercare
	 * @return {Object} Ritorna il wNode corrispondente oppure ritorna false
	 * nel caso la ricerca abbia avuto esito negativo
	 */
	var lookForId = function(eid,wNodeArr){
		for (ind in wNodeArr)
		{
			if (wNodeArr[ind].eidentifier == eid) 
				return wNodeArr[ind];
			else {
				var res = lookForId(eid, wNodeArr[ind].sons);
				if (res != false) 
					return res;
			}
		}
		return false;
	}
	
	/**
	 * Controlla se l'oggetto ha le determinate proprieta`
	 * @param {Object} wid Identificativo del work
	 * @param {Object} publisher epublisher
	 * @return {Object} Ritorna true se le proprieta` corrispondono, false altrimenti
	 */
	this.check = function(wid,publisher)
	{
		if (roots.length == 0) return false;
		if ((wid == widentifier) && (roots[0].getValOf('epublisher') == publisher)) return true;
		else false;
	}
	
	/**
	 * Reperisce informazioni sul work
	 * @param {Object} infor Nome del campo del work da reperire
	 * @param {Object} index Eventuale indice dell'elemento desiderato (eventualmente null)
	 * @return {Object} Ritorna il valore del testo contenuto nel campo
	 */
	this.retriveInfo = function(infor,index)
	{
		if (index == null) index = 0;
		return workInformations.getElementsByTagName(infor)[index].innerText;
	}
	
	
	/** COSTRUTTORE */
	dataSource.query( ("widentifier=" + widentifier),
		function(xhr){
			response = xhr.responseXML;
			metadati = response.getElementsByTagName('metadati');
			workInformations = metadati[0].getElementsByTagName('work')[0];
			for (index in metadati)
			{
				var newNode = wNode(metadati[index].getElemntsByTagName('expression')[0]);
				if (newNode.getValOf('erelation') == "")
					roots.push(newNode);
				else {
					var res = lookForId(esource,roots);
					if (res == false) 
						pending.push(res);
					else {
						newNode.father = res;
						res.addSon(newNode);
					}
				}
			}
			
			while (pending.length > 0)
			{
				var node = pending.pop();
				var res = lookForId(node.getValOf('erelation'),roots);
				if (res == false) 
					pending.push(res);
				else {
					newNode.father = res;
					res.addSon(node);
				}
			}
			
			/* Giunti qui, siamo pronti */
			if (onready != null) onready(this);
		});
	
}
